博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ASP.NET 调味品:AJAX
阅读量:5154 次
发布时间:2019-06-13

本文共 13994 字,大约阅读时间需要 46 分钟。

发布日期 : 1/6/2006 | 更新日期 : 1/6/2006

Karl Seguin

适用于:

AJAX(异步 JavaScript 和 XML)
Microsoft AJAX.NET
Microsoft ASP.NET

摘要:了解如何将 AJAX(异步 JavaScript 和 XML)用于您的 Microsoft ASP.NET 应用程序,使其互动性更强、响应更及时。

下载本文的代码示例

下载本文的代码示例

本页内容

简介

自从开始 Web 编程以来,在 Web 应用程序和桌面应用程序之间一直存在着许多取舍。例如,人们通常认为 Web 应用程序提供的用户界面类型没有桌面应用程序提供的用户界面类型那样丰富。另一方面,Web 应用程序是独立的平台,其开发机制比较简单。提供响应更及时的应用程序看似是一项简单的任务,但对于 Web 开发人员来说却是一直以来需要攻克的领域。

传统意义上,只能通过向 Web 服务器提交新的请求来检索对用户输入所做的响应。在某些情况下,开发人员可以使用 JavaScript 在客户端上加载所有响应,从而提供更好的用户体验。此技术的常见示例是基于所选国家/地区来动态加载一系列州或省。遗憾的是,在很多情况下,不将所有响应都返回或加载到 JavaScript 要更好。返回操作会使过多的 UI 断开连接,或在客户端上需要过量的数据,这经常导致生成不易读的 JavaScript。AJAX 提供了一种新的中间选择,能够在维持及时响应和灵活性的同时利用基于服务器的应用程序。

什么是 AJAX?

AJAX 是 Asynchronous JavaScript And XML(异步 JavaScript 和 XML)的缩写,它不是一项技术,而是很多技术的集合。AJAX 使用通信技术(通常为 SOAP 和 XML)发送和接收对服务器的异步请求/响应,然后利用显示技术(JavaScript、DOM、HTML 和 CSS)处理响应。如今,使用 AJAX 的应用程序是合法的,因为多数浏览器都支持这项必需的技术。有关 AJAX 更详细的定义,请访问 (英文)。

AJAX 到底是什么?AJAX 使您能够通过 JavaScript 调用执行服务器端方法,而不需要刷新浏览器。将它视为发生于用户后台的小型请求/响应。如果您仍不清楚 AJAX 是什么,请看 Google 上的两个常见示例:(英文)和 (英文)。如果您不熟悉 AJAX,这两个应用程序的响应会使您有点兴奋。

用于 ASP.NET 的 AJAX

很多因素促使 AJAX 应运而生。您可能不想花费几个小时或几天来了解 AJAX 的内部原理,而是更希望现在就开始创建启用了 AJAX 的应用程序,来满足现有需求(如果您确实想知道 AJAX 内部工作原理,我肯定不是可以询问的人)。开发人员可以用来快速入门的工具有很多。不过我们将特别关注由 Michael Schwarz 编写的源代码开放的免费 Ajax.NET。Ajax.NET 考虑到所有的实现细节是基于 .NET 的,并且能够被扩展。Microsoft ASP.NET 2.0 通过(英文)引入了独具特色的异步回调,并且(英文)代号为“Atlas”的 AJAX 正在实现中。

术语可能有些混乱,但是当我介绍 AJAX 时,就是在介绍从客户端异步调用服务器端函数的整体框架。提到 Ajax.NET 时,我是指能够帮助您创建利用 AJAX 框架的解决方案的特定实现。

要了解有关 ASP.NET 2.0 客户端回调功能的详细信息,请访问 (英文)。

手头的 AJAX

本文的剩余部分将使用 Ajax.NET 着重介绍三个利用 AJAX 功能的有意义的示例。本指南将包含以 Microsoft C# 和 Microsoft Visual Basic .NET 编写的代码,有时同时提供这两种代码,有时仅提供其中一种代码。实现所有这一切的代码很容易,C# 开发人员能够很容易地遵循仅以 Visual Basic .NET 编写的代码,反之亦然!本文包含的示例 C# 和 Visual Basic .NET 项目可供下载,并提供工作代码和运行代码。在学习示例以前,首先需要了解如何安装和使用 Ajax.NET。

Ajax.NET

AJAX.NET (英文)和(英文)对开发人员快速入门非常有用。在介绍使用此技术的一些具体示例之前,我们将简要回顾您所需要知道的核心步骤。

首先从 (英文)上下载并解压缩 AJAX 文件,然后按照您的喜好在 Visual Basic .NET 或 C# 中创建新的 ASP.NET 项目,再向 AJAX.dll 文件(英文)。唯一的额外配置步骤是在 <system.web> 元素中(位于 web.config 文件中)添加以下代码。

... ...

为了使服务器端函数在 JavaScript 中可用,必须做两件事情。首先,要使用的函数必须标有 Ajax.AjaxMethodAttribute。其次,在页加载事件期间,必须通过调用 Ajax.Utility.RegisterTypeForAjax 来注册包含这些函数的类。听起来似乎有些复杂,但请不必担心;实际上只需要在代码中多加两行。让我们看一个示例。

//C#public class Sample :System.Web.UI.Page{private void Page_Load(object sender, System.EventArgs e) {//注册我们感兴趣的包含服务器端函数//的类Ajax.Utility.RegisterTypeForAjax(typeof(Sample)); }[Ajax.AjaxMethod()]public string GetMessageOfTheDay() {return "Experience is the mother of wisdom"; }}'VB.NETPublic Class SampleInherits System.Web.UI.PagePrivate Sub Page_Load(sender AsObject, e As EventArgs) Handles MyBase.Load'注册我们感兴趣的包含服务器端函数'的类Ajax.Utility.RegisterTypeForAjax(GetType(Sample))End Sub 
_Public Function GetMessageOfTheDay() As StringReturn "Experience is the mother of wisdom"End FunctionEnd Class

以上示例首先告知 Ajax.NET 在 Sample 类中查找友好的 Ajax 方法。它正好是与实际页相同的类,但是它可以是任意 .NET 类,或可以注册多个类。然后,Ajax.NET 将浏览指定的类,来查找标有 AjaxMethodAttribute 的所有方法,其中 Sample 类有一个 GetMessageOfTheDay

完成后,剩下唯一要做的就是在 JavaScript 中使用它。Ajax.NET 自动创建与注册的类具有相同名称的 JavaScript 变量(在本例中将为 Sample),它提供与 AjaxMethod 具有相同名称的函数(在本例中为 GetMessageOfTheDay)。如下所示。

除了 JavaScript 回调函数以外,JavaScript GetMessageOfTheDay 还需要与其服务器端对应部分相同的参数(在此情况下,没有参数),以便在完成时执行并传递响应。在此,我们看到 AJAX 在工作时的异步特性,因为对 GetMessageOfTheDay 的调用不阻碍执行其他 JavaScript 代码,也不阻碍用户继续在页上进行操作。完成服务器端处理时,Ajax.NET 调用指定的回调函数 GetMessageOfTheDay_CallBack,并向其传递由服务器端返回值组成的响应。

服务器端代码和 JavaScript 代码之间的映射可能有些混乱。图 1 简要显示了服务器端代码和 JavaScript 代码,以及两者之间的映射。

1
:服务器端代码和
JavaScript
代码之间的映射

当然令人感兴趣的 Ajax.NET 还有更多内容值得介绍,例如对 .NET 类型的支持和丰富的回调响应(它不仅仅是值)。以下示例将会重点介绍某些功能,希望帮助您理解 AJAX 如何帮助您创建成功的应用程序。

示例 1 :链接的下拉列表

本文的开始简要地讨论了用于链接两个 DropDownList 的两种传统方法。当选定的索引更改时,返回页;或者将所有可能的数据加载到 JavaScript 数组并动态显示。希望您可以看到 AJAX 如何替代这两种解决方案。

首先,让我们来看一下我们的数据界面,并从该数据界面驱动示例。我们的数据访问层将提供两种方法:第一种方法将检索系统支持的国家/地区的列表,第二种方法将获取国家/地区 ID 并返回州/省的列表。由于这是纯数据访问,因此我们只需要使用方法。

//C#public static DataTable GetShippingCountries();public static DataView GetCountryStates(int countryId);'VB.NETPublic Shared Function GetShippingCountries() As DataTablePublic Shared Function GetCountryStates(ByVal countryId As Integer)As DataView

现在,让我们转到相反面,创建简单的 Web 窗体。

Page_Load 事件同样简单,和前述的 Web 窗体一样。我们使用数据访问层来检索可用的国家/地区,并将其绑定到 countriesDropDownList 中。

//C#if (!Page.IsPostBack){countries.DataSource = DAL.GetShippingCountries();countries.DataTextField = "Country";countries.DataValueField = "Id";countries.DataBind();countries.Items.Insert(0, new ListItem("Please Select", "0"));}

通常,代码到此为止。首先,我们将创建要从 JavaScript 调用的服务器端函数。

'VB.NET
_Public Function GetStates (ByVal countryId As Integer) As DataViewReturn DAL.GetCountryStates(countryId)End Function

这与您通常使用的任何其他函数一样:它需要我们想要获得的国家/地区的 ID,并将该请求传递给 DAL。唯一的不同是我们已使用 AjaxMethodAttribute 标记了该方法。最后剩余的服务器端步骤是通过调用 RegisterTypeForAjax 使用 Ajax.NET 来注册包含上述方法的类(在此情况下,是我们的下面的代码)。

//C#Ajax.Utility.RegisterTypeForAjax(typeof(Sample));'VB.NETAjax.Utility.RegisterTypeForAjax(GetType(Sample))

我们已基本完成;剩余的就是从 JavaScript 调用 GetStates 方法和处理响应。当用户从国家/地区列表中选择新项时,我们想在逻辑上调用 GetStates。为此,我们将触发 JavaScript onChange 事件。这样就稍微更改了我们的 Web 窗体代码。

JavaScript LoadStates 函数将负责通过由 Ajax.NET 创建的代理发出异步请求。请记住,默认情况下,Ajax.NET 创建的代理的格式为 <RegisteredTypeName>.<ServerSideMethodName>。在我们的示例中,将为 Sample.GetStates。我们还想传入国家/地区 ID 参数和完成服务器端函数后 Ajax.NET 应调用的回调函数。

//JavaScriptfunction LoadStates(countries){var countryId = countries.options[countries.selectedIndex].value;Sample.GetStates(countryId, LoadStates_CallBack);}

最后一个步骤是处理我们的 LoadStates_CallBack 函数中的响应。Ajax.NET 最有用的功能大概是它支持很多 .NET 类型(我已经多次提到这一点)。回顾一下返回 DataView 的服务端函数。JavaScript 知道 DataView 什么?什么也不知道,但是 JavaScript 是面向对象的语言,而且 Ajax.NET 不只能够创建与 .NET DataView 相似的对象,还能将该函数返回的值映射到 JavaScript 副本。您应该记住 JavaScript DataView 只不过是实际 DataView 的副本,目前除了能够遍历行和访问列值以外不支持其他更多功能(例如设置 RowFilter 或 Sort 属性的功能)。

function LoadStates_CallBack(response){//如果服务器端代码出现异常if (response.error != null) {//我们应该能做得更好alert(response.error); return; }var states = response.value;//如果不是我们所希望的响应if (states == null || typeof(states) != "object") {return; }//获得州下拉列表var statesList = document.getElementById("states");statesList.options.length = 0; //重置州下拉列表//记住,其长度不是 JavaScript 中的 Lengthfor (var i = 0; i < states.length; ++i) {//如命名属性一样公开行的列statesList.options[statesList.options.length] =new Option(states[i].State, states[i].Id); }}

经过一些错误检查之后,前面的 JavaScript 获得州下拉列表,遍历响应的值,并动态地将选项添加到该下拉列表中。代码清晰、简单并与 C# 和 Visual Basic .NET 非常相似。就我个人而言(作为基于服务器端变量创建了 JavaScript 数组并将它们链接在一起的开发人员),我还要一段时间才能相信它真的起作用了。

有一个可能不太明显的主要问题。由于 DropDownList 是在 JavaScript 中动态创建的,因此它的项不属于 ViewState,并且不被维护。这意味着按钮的 OnClick 事件处理程序需要进行一些额外的修改。

'VB.NETPrivate Sub submit_Click(sender As Object, e As EventArgs)Dim selectedStateId As String = Request.Form(states.UniqueID)'应进行一些用户验证...states.DataSource =DAL.GetCountryStates(Convert.ToInt32(countries.SelectedIndex))states.DataTextField = "State"states.DataValueField = "Id"states.DataBind()states.SelectedIndex = states.Items.IndexOf(states.Items.FindByValue(selectedStateId))End Sub

首先,我们不能使用 states.SelectedValue 属性,而必须使用 Request.Form。其次,如果我们想向用户重新显示该列表,需要重新使用相同的数据访问方法绑定州 DropDownList。最后,必须以编程方式设置选定的值。

示例 2 :文档锁定程序

对于下一个示例,我们将引入更加完整的功能,然后使用 AJAX 改进它。此示例属于简单的文档管理系统。如任何正式的文档管理系统一样,我们必须提供并发管理。即,我们需要一种方法来处理两个用户尝试编辑同一个文档的问题。我们将通过创建某种类型的锁定机制,来使正在编辑的文档不能再由另一个用户编辑,从而达到上述目的。我们将利用 AJAX 让用户有更愉快的锁定机制体验。首先,我们将创建用户尝试编辑但无法编辑(因为其他用户正在编辑该文档)的文档队列,当这些文档可用时自动通知用户。其次,我们将确保当用户关闭其浏览器或导航到其他位置时,解除对文档的锁定。后一个功能帮助确保文档不会永远处于锁定状态。为此,在本指南中,我们将跳过与 AJAX 实现不相关的功能;但是,可下载项目包含所有功能。

首先,当用户尝试编辑文档时,我们会尝试对其建立排它锁,如果失败,我们会将此文档添加到用户的队列然后使其返回到主页。对此处的 AJAX 没有什么特别之处,但是我们将查看一下代码,以便给出示例必要的上下文。在用于编辑的 PageOnLoad 事件中,添加以下代码。

//C#if (!Page.IsPostBack){//应验证用户输入Document document = GetDocument(Request.QueryString["id"]);//我们拥有此文档,但不能编辑它!if (!Locker.AcquireLock(document)) {//让我们将它添加到要查看的用户文档列表User.CurrentUser.AddDocumentToQueue(document.DocumentId);Response.Redirect("DocumentList.aspx"); }//好了,我们拥有此文档,并且可以编辑它 //...}

关键行的位置是将文档添加到当前用户的队列中(这会将文档添加到会话中)。接下来,我们将创建用户控件,该控件可以被放置到任何页上,用于当队列文档可用时通知用户。此用户控件将包含一个 AJAX 方法以及注册 AJAX 的类所需的代码。

'VB.NETPrivate Sub Page_Load(s As Object, e As EventArgs) Handles MyBase.LoadAjax.Utility.RegisterTypeForAjax(GetType(UnlockNotifier))End Sub'遍历队列文档并检查它们是否可用
_Public Function GetUnlockedDocuments() As DocumentCollection'获得属于用户的所有队列文档的 IDDim queuedDocument As ArrayList = User.CurrentUser.DocumentQueueDim unlocked As DocumentCollection = New DocumentCollectionFor Each documentId As Integer In queuedDocumentIds'如果队列文档不再被锁定If Not Locker.IsLocked(documentId) Thenunlocked.Add(Document.GetDocumentById(documentId))End IfNextReturn unlockedDocumentsEnd Function

现在需要的是使一些 JavaScript 发出请求并处理响应。我们将基于响应在要动态创建的表中放置已发布的文档信息(如果有)。为此,我们将开始编写 HTML。

如果没有可用的文档(或是没有为该用户列出文档),我们使用 DIV 标记隐藏所有内容,用 TABLE 标记来显示结果。我们将使用轮询系统来检查是否存在任何可用的队列文档。一般来说,这意味着我们将在稍后一段时间内一直调用服务器端方法,并显示结果。在加载页面时仅发生第一次调用,每隔 X 秒发生后续调用。

剩下的就是处理响应。这与以前示例中的代码相似。首先,检查是否存在错误,获得响应,遍历可用的文档,动态创建 HTML,在这种情况下,向表中添加行和列。

function PollQueue_CallBack(response){var notifyBox = document.getElementById("notifyBox");var notifyTable = document.getElementById("notifyTable");//如果我们无法找到表通知框if (notifyBox == null || notifyTable == null)  {return;  }//如果服务器端代码出现异常if (response.error != null)  { notifyBox.style.display = "none"; alert(response.error); //我们应该能做得更好return;  }  var documents = response.value;//如果不是我们所希望的响应if (documents == null || typeof(documents) != "object")  {notifyBox.style.display = "none";return;  }  for (var i = 0; i < notifyTable.rows.length; ++i)  {notifyTable.deleteRow(i);  }for(var i = 0; i < documents.length; ++i)  {    var row = notifyTable.insertRow(0);row.className = "Row" + i%2;var cell = row.insertCell(0);cell.innerHTML = documents[i].Title;cell = row.insertCell(1);var date = documents[i].Created;cell.innerHTML = date.getDay() + "/" + date.getMonth() + "/" + date.getYear();cell = row.insertCell(2);cell.innerHTML = "edit";  } notifyBox.style.display = "block";}

我们要看到的最后一个快速改进是当用户关闭浏览器、导航到其他链接或单击“后退”按钮时,将自动解除文档锁定。通常,可以通过触发 JavaScript OnBeforeUnLoad 事件或 OnUnload 事件达到此目的,这会打开新的小型弹出式窗口,该弹出式窗口在加载页面时做一些清理然后自行关闭。您自己可以使用弹出式窗口,但是其他人则不能使用,它将导致弹出式窗口受阻并使文档永久保持锁定状态。要解决此问题,我们仍需要两个 JavaScript 事件,但是并不是启动弹出式窗口,而是将通过 AJAX 执行服务器端方法。在用于编辑文档的页上(即,放置锁的页),我们添加一些简单的 JavaScript。

在这里,DocumentId 是在后面的代码中定义和设置的变量。另外,我们可以在会话中存储 DocumentId,并在服务器端 ReleaseDocument 中访问。通常,ReleaseDocument 从锁定的文档列表中删除文档。

示例 3 :论坛主题搜索

我们要看的最后一个示例是对现有应用程序的修改。我首次听到这个想法是 (英文)设想在 (英文)里添加一个功能。目的是尝试帮助用户自己找到问题的答案,以及限制重复发布的数量。一般来说,用户在论坛中提出新问题时,他或她会输入主题和问题。他们通常都不会先进行搜索,来查看是否已经提出和回答过该问题。输入 AJAX。用户输入主题(并将 Tab 键移出该字段)后,我们基于该主题异步搜索论坛,并适时地向用户显示结果。有时这些结果会有帮助,有时候则不会。

为使结果有帮助,我们将修改 asp.NETPRO Reader's Choice Award for Best Forum Application, CommunityServer。可下载的示例中不包含这一部分(或论坛)的代码,但是您能在 (英文)学到关于 CommunityServer 的更多知识,并且可在其中应用下面这些代码片断。

安装 CommunityServer 并配置 Ajax.NET(已将引用和处理程序添加到 web.config)后,我们只需要进行一些更改就可以获得所需的功能。首先,我们转到 CommunityServerForums 项目中的 CreateEditPost.cs 文件。将它视为此页的后面的代码,其中用户可以添加新的发布。下面我们将添加启用了 AJAX 的函数。

//C#[Ajax.AjaxMethod()]public static ArrayList Search(string search){SearchQuery query = new SearchQuery();query.PageIndex = 0; //获得前 10 个结果query.PageSize = 10;query.UserID = Users.GetUser().UserID;query.SearchTerms = search;return new ForumSearch().GetSearchResults(query).Posts;}

我们能够利用已经在 CommunityServer 中创建的搜索功能,只需要我们的函数能应用它。如往常一样,类型必须使用 Ajax.NET 注册。我们将在同一文件的 InitializeSkin 函数(将其视为 Page_Load)中进行此操作。

//C#Ajax.Utility.RegisterTypeForAjax(typeof(CreateEditPost));

在转跳到 JavaScript 之前,我们需要进行最后的服务器端更改。返回到 Ajax.NET 的自定义类(例如我们正在返回的 ArrayList 所包含的 ForumPost)必须标有 Serializable 属性。我们要做的是转到 CommunityServerForums 项目中的 Components/ForumPost.cs 文件,并添加此属性。

//C#[Serializable]public class ForumPost :Post{ ...}

显示时,我们仅需要修改 CommunityServerWeb 项目中的 Themes/default/Skins/View-EditCreatePost.cs。首先,我们将触发主题文本框的 onBlur 事件。

接着,我们编写 JavaScript Search 方法,以便调用服务器端 Search

var oldValue = '';function Search(value){ //不要再次搜索刚搜索过的内容//如果用户向后或向前移动 Tab 键将会发生if (value != oldValue)  {CreateEditPost.Search(value, Search_CallBack);oldValue = value;  }}

最后,剩下的就是处理响应。由于上一个示例介绍了在表中显示结果的稍微正规的方式,我们将仅仅创建一些动态的 HTML,并将它粘贴到虚拟的 DIV 中。

function Search_CallBack(response){//由于没有结果时搜索功能将自动重定向,//因此,我们不能使用 response.error。var results = response.value;//如果我们没有获得结果if (results == null) {return; }//我们用于放置结果的 DIVvar someDiv = document.getElementById("someDiv");var html = "";for (var i = 0; i < results.length; ++i) {var result = results[i];html += "";   html += result.Subject;html += "
" }someDiv.innerHTML = html;}

通过对 CommunityServer 应用程序的三个文件(加上用于配置的 web.config)稍微进行修改,我们可以添加一些非常有用的功能。但是,只向现有的应用程序添加启用 AJAX 功能时要小心操作。正在进行实际搜索的预先存在的 ForumSearch 类可能并不是为我们介绍的使用类型设计的。我们的代码很可能会导致执行一些额外的搜索,影响可能会很显著。

AJAX 与您

AJAX 如何以及哪里适合您的应用程序,以及是否已经存在要根据情况而定。尽管我们已经看到使用 Ajax.NET 可以轻松地创建启用 AJAX 的解决方案,但还存在一些其他的注意事项。一个需要着重关注的问题是对您的应用程序的整体体系结构和可维护性的影响。AJAX 会进一步模糊系统的各层之间的界限,显著影响显示层、显示逻辑层和业务层。这不是 AJAX 本身的问题,而是使用方式的问题。只要您知道它很容易导致各层之间的某些冲突,并适当操作,就不会产生问题。

使用 AJAX 的应用程序更难于维护吗?答案主要取决于您已经使用的 JavaScript 的数量,以及您组织和维护它的好坏程度。很多开发人员认为 JavaScript 难于编写、测试和调试(不是因为 JavaScript 本身,而是因为工具支持和开发人员的知识)。如果您当前正在使用 JavaScript 实现链接的下拉列表,并切换到 AJAX,您的代码可能较为容易维护(Ajax.NET 对 .NET 类型和数组的支持是重要原因)。但是,如果您使用返回方式来实现,现在您将向您的应用程序 (JavaScript) 引入崭新的语言。您将必须处理这样的情况:存在某些不参与 ViewState 的数据(这一点我们在按钮单击事件中可以看到)。

另一个需要考虑的是 AJAX 对您的网站可用性的影响。即使 AJAX 最后能创建响应更及时的界面,开发人员仍需要注意两件事情。首先,很明显 AJAX 依赖 JavaScript。我们都知道一些用户禁用 JavaScript,一些标准(例如加拿大政府 Common Look and Feel [考虑加拿大的 508])要求网站使用 JavaScript 来运行,或不使用它来运行。因此,您不应假定 AJAX 功能正在运行。如果 AJAX 功能不可用,则应使您的应用程序退回到更普通的 Web 处理。其次,AJAX 应用程序可能不熟悉(即使它具有较高级别)用户习惯使用应用程序的方式。例如,通过 AJAX 执行不同功能的页可能不以用户认为的方式表现“后退”按钮、“收藏夹”菜单和其他浏览器功能。

结论

AJAX 不只是令人兴奋的即将面世的技术,它是具体的框架,在建立 Web 应用程序时可以采用它来解决每天遇到的问题。Ajax.NET 使 ASP.NET 开发人员轻松掌握 AJAX。我们看到的三个示例和可下载的项目可以帮助您了解如何使用 AJAX 和 Ajax.NET。您还可以利用这些示例来尝试一些自己的想法。AJAX 不仅可以创建简洁和强大的应用程序,它还可以使您提高客户满意度和竞争优势。正在讨论的 Atlas 的一些高级概念可能显著改进我们提供的产品。就个人而言,我见过的最佳的 AJAX 实现非常轻便合适。您自己的实现应为您的用户提供同样积极的体验。但是,对于某个具体问题,记住 AJAX 可能不是唯一的解决方案,也可能不是最佳的解决方案。现在,让我们证明 ASP.NET 社区是首屈一指的,让我们收拾屋子吧。

关于作者

Karl Seguin 将他的大部分时间用在 Microsoft ASP.NET 新闻组,帮助其他开发人员并寻找和编写帮助性的主题。当他不工作或不提供帮助时,他喜欢无情地清洁 Gnomish 灾难的 Azeroth。

转载于:https://www.cnblogs.com/Godblessyou/archive/2010/07/16/1779193.html

你可能感兴趣的文章
【算法导论第13章】红黑树
查看>>
scrollLeft. float
查看>>
浅说项目管理中的Action以及3W1P原则
查看>>
迭代器模式
查看>>
Subscription
查看>>
用注解给映射视图的类创建联合主键
查看>>
cannot load such file -- readline
查看>>
JDK8 新特性流式数据处理
查看>>
Linux 动态库剖析
查看>>
Xplico
查看>>
Eclipse 调试器
查看>>
Docker环境搭建,K8s
查看>>
Python3爬虫(六) 解析库的使用之Beautiful Soup
查看>>
Python实例:11~20例
查看>>
ORACLE1.13-综合例子应用01
查看>>
js,同意后,才可已点击注册按钮
查看>>
MySQL check the manual that corresponds to your MySQL server version for the right syntax错误
查看>>
[学习总结]6、Android异步消息处理机制完全解析,带你从源码的角度彻底理解
查看>>
java内部类实现多继承
查看>>
python thread 多线程
查看>>